package com.castle.fortress.admin.goods.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.goods.dto.GoodsCategoryDto;
import com.castle.fortress.admin.goods.entity.GoodsCategoryEntity;
import com.castle.fortress.admin.goods.service.GoodsCategoryService;
import com.castle.fortress.admin.utils.ExcelUtils;
import com.castle.fortress.common.entity.DynamicExcelEntity;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.utils.ConvertUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品分类表 控制器
 *
 * @author majunjie
 * @since 2021-11-22
 */
@Api(tags = "商品分类表管理控制器")
@Controller
public class GoodsCategoryController {
    @Autowired
    private GoodsCategoryService goodsCategoryService;

    /**
     * 商品分类表的分页展示
     *
     * @param goodsCategoryDto 商品分类表实体类
     * @param current          当前页
     * @param size             每页记录数
     * @return
     */
    @ApiOperation("商品分类表分页展示")
    @GetMapping("/goods/goodsCategory/page")
    @ResponseBody
    @RequiresPermissions("goods:goodsCategory:pageList")
    public RespBody<IPage<GoodsCategoryDto>> pageGoodsCategory(GoodsCategoryDto goodsCategoryDto, @RequestParam(required = false) Integer current, @RequestParam(required = false) Integer size) {
        Integer pageIndex = current == null ? GlobalConstants.DEFAULT_PAGE_INDEX : current;
        Integer pageSize = size == null ? GlobalConstants.DEFAULT_PAGE_SIZE : size;
        Page<GoodsCategoryDto> page = new Page(pageIndex, pageSize);
        IPage<GoodsCategoryDto> pages = goodsCategoryService.pageGoodsCategoryExtends(page, goodsCategoryDto);

        return RespBody.data(pages);
    }

    /**
     * 商品分类表的列表展示
     *
     * @param goodsCategoryDto 商品分类表实体类
     * @return
     */
    @ApiOperation("商品分类表列表展示")
    @GetMapping("/goods/goodsCategory/list")
    @ResponseBody
    public RespBody<List<GoodsCategoryDto>> listGoodsCategory(GoodsCategoryDto goodsCategoryDto) {
        List<GoodsCategoryDto> list = goodsCategoryService.listGoodsCategory(goodsCategoryDto);
        return RespBody.data(list);
    }

    /**
     * 商品分类树列表
     *
     * @return
     */
    @ApiOperation("商品分类树列表")
    @GetMapping("/goods/goodsCategory/treeList")
    @ResponseBody
    public RespBody<List<GoodsCategoryDto>> treeList() {
        List<GoodsCategoryDto> list = goodsCategoryService.treeList();
        return RespBody.data(list);
    }

    /**
     * 商品分类表保存
     *
     * @param goodsCategoryDto 商品分类表实体类
     * @return
     */
    @ApiOperation("商品分类表保存")
    @PostMapping("/goods/goodsCategory/save")
    @ResponseBody
    @RequiresPermissions("goods:goodsCategory:save")
    public RespBody<String> saveGoodsCategory(@RequestBody GoodsCategoryDto goodsCategoryDto) {
        if (goodsCategoryDto == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        GoodsCategoryEntity goodsCategoryEntity = ConvertUtil.transformObj(goodsCategoryDto, GoodsCategoryEntity.class);
        goodsCategoryEntity.setLevel(getCategoryLevel(goodsCategoryDto.getParentId()));
        if (goodsCategoryService.save(goodsCategoryEntity)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    private int getCategoryLevel(Long parentId) {
        int i = 1;
        // 判断分类是在第几级
        if (parentId != null) {
            i++;
            List<GoodsCategoryEntity> list = goodsCategoryService.list();
            Map<String, GoodsCategoryEntity> map = new HashMap<>();
            for (GoodsCategoryEntity entity : list) {
                map.put("" + entity.getId(), entity);
            }
            GoodsCategoryEntity entity = map.get(parentId + "");
            while (entity != null && entity.getParentId() != null) {
                i++;
                entity = map.get(entity.getParentId() + "");
            }
        }
        return i;
    }

    /**
     * 商品分类表编辑
     *
     * @param goodsCategoryDto 商品分类表实体类
     * @return
     */
    @ApiOperation("商品分类表编辑")
    @PostMapping("/goods/goodsCategory/edit")
    @ResponseBody
    @RequiresPermissions("goods:goodsCategory:edit")
    public RespBody<String> updateGoodsCategory(@RequestBody GoodsCategoryDto goodsCategoryDto) {
        if (goodsCategoryDto == null || goodsCategoryDto.getId() == null || goodsCategoryDto.getId().equals(0L)) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        GoodsCategoryEntity goodsCategoryEntity = ConvertUtil.transformObj(goodsCategoryDto, GoodsCategoryEntity.class);
        // 若修改了分类的上级为自己或自己的子分类 则禁止修改
        List<GoodsCategoryDto> childrenList = null;
        if (goodsCategoryDto.getParentId() != null) {
            if (goodsCategoryDto.getId().equals(goodsCategoryDto.getParentId())) {
                return RespBody.fail("操作失败,分类上级不能为自己或自己的下级分类");
            }
            childrenList = goodsCategoryService.allChildrenListById(goodsCategoryEntity.getId());
            List<GoodsCategoryDto> list = childrenList.stream()
                    .filter(dto -> dto.getId().equals(goodsCategoryDto.getParentId()))
                    .collect(Collectors.toList());
            if (list.size() > 0) {
                return RespBody.fail("操作失败,分类上级不能为自己或自己的下级分类");
            }
        }
        int newLevel = getCategoryLevel(goodsCategoryDto.getParentId());
        int oldLevel = goodsCategoryDto.getLevel();
        goodsCategoryEntity.setLevel(newLevel);
        if (goodsCategoryService.updateById(goodsCategoryEntity)) {
            // 若提交的父类id为空 则移除上级id
            if (goodsCategoryEntity.getParentId() == null) {
                goodsCategoryService.deletePidById(goodsCategoryDto.getId());
            }
            // 若等级发生改变 所有下级也更新等级
            if (newLevel != goodsCategoryDto.getLevel()) {
                int addValue = newLevel - oldLevel;
                if (childrenList == null) {
                    childrenList = goodsCategoryService.allChildrenListById(goodsCategoryEntity.getId());
                }
                if (childrenList.size() > 0) {
                    childrenList.forEach(e -> e.setLevel(e.getLevel() + addValue));
                }
                goodsCategoryService.updateBatchById(ConvertUtil.transformObjList(childrenList, GoodsCategoryEntity.class));
            }
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 递归检查分类id 是否属于自己的下级
     *
     * @return
     */
    private boolean examinePid(List<GoodsCategoryDto> list, Long id) {
        for (GoodsCategoryDto dto : list) {
            if (dto.getId().equals(id)) {
                return true;
            } else {
                if (dto.getChildren() != null && dto.getChildren().size() > 0) {
                    if (examinePid(dto.getChildren(), id)) {
                        return true;
                    }
                }

            }
        }
        return false;
    }

    /**
     * 商品分类表删除
     *
     * @param id
     * @return
     */
    @ApiOperation("商品分类表删除")
    @PostMapping("/goods/goodsCategory/delete")
    @ResponseBody
    @RequiresPermissions("goods:goodsCategory:delete")
    public RespBody<String> deleteGoodsCategory(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        List<GoodsCategoryDto> list = goodsCategoryService.childrenListById(id);
        if (list.size() > 0) {
            return RespBody.fail("请先删除子分类");
        }
        if (goodsCategoryService.removeById(id)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 商品分类表批量删除
     *
     * @param ids
     * @return
     */
    @ApiOperation("商品分类表批量删除")
    @PostMapping("/goods/goodsCategory/deleteBatch")
    @ResponseBody
    @RequiresPermissions("goods:goodsCategory:deleteBatch")
    public RespBody<String> deleteGoodsCategoryBatch(@RequestBody List<Long> ids) {
        if (ids == null || ids.size() < 1) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (goodsCategoryService.removeByIds(ids)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 商品分类表详情
     *
     * @param id 商品分类表id
     * @return
     */
    @ApiOperation("商品分类表详情")
    @GetMapping("/goods/goodsCategory/info")
    @ResponseBody
    @RequiresPermissions("goods:goodsCategory:info")
    public RespBody<GoodsCategoryDto> infoGoodsCategory(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        GoodsCategoryDto goodsCategoryDto = goodsCategoryService.getByIdExtends(id);

        return RespBody.data(goodsCategoryDto);
    }

    /**
     * 动态表头导出 依据展示的字段导出对应报表
     *
     * @param dynamicExcelEntity
     * @param response
     * @throws Exception
     */
    @PostMapping("/goods/goodsCategory/exportDynamic")
    @ApiOperation("动态表头导出，依据展示的字段导出对应报表")
    public void exportDynamic(@RequestBody DynamicExcelEntity<GoodsCategoryDto> dynamicExcelEntity, HttpServletResponse response) throws Exception {
        List<GoodsCategoryDto> list = goodsCategoryService.listGoodsCategory(dynamicExcelEntity.getDto());
        //字典、枚举、接口、json常量等转义后的列表数据 根据实际情况初始化该对象，null为list数据直接导出
        List<List<Object>> dataList = null;
        /**
         * 根据实际情况初始化dataList,可参照 com.castle.fortress.admin.system.controller.TmpDemoController类中方法：exportDynamic
         */
        ExcelUtils.exportDynamic(response, dynamicExcelEntity.getFileName() + ".xlsx", null, list, dynamicExcelEntity.getHeaderList(), dataList);
    }


}
